namespace SimpleWebServices.Xml
{
    using System.Xml;
    using System.Xml.Serialization;
    using System.Xml.XPath;
    using SimpleWebServices;
    using Xunit;

    public sealed class XLinkFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<XLink>()
                .DerivesFrom<ValueObject<XLink>>()
                .IsConcreteClass()
                .IsUnsealed()
                .HasDefaultConstructor()
                .XmlRoot("link")
                .Result);
        }

        [Fact]
        public void deserialize()
        {
            XLink actual = (
                "<link xmlns:xlink='http://www.w3.org/1999/xlink'" +
                    " xlink:href='#abc123'" +
                    " xlink:title='Example'" +
                    " xlink:type='simple' />").Deserialize<XLink>();

            Assert.NotNull(actual);

            Assert.Equal<string>("#abc123", actual.Href);
            Assert.Equal<string>("Example", actual.Title);
            Assert.Equal<string>("simple", actual.Type);
        }

        [Fact]
        public void deserializeEmpty()
        {
            XLink actual = "<link xmlns:xlink='http://www.w3.org/1999/xlink' />".Deserialize<XLink>();

            Assert.NotNull(actual);

            Assert.Null(actual.Href);
            Assert.Null(actual.Title);
            Assert.Null(actual.Type);
        }

        [Fact]
        public void serialize()
        {
            XLink obj = new XLink
            {
                Href = "#abc123",
                Title = "Example",
                Type = "simple"
            };

            XPathNavigator navigator = obj.Serialize().CreateNavigator();

            Assert.True((bool)navigator.Evaluate("1=count(/link)"));

            XmlNamespaceManager namespaces = new XmlNamespaceManager(navigator.NameTable);
            namespaces.AddNamespace("xlink", "http://www.w3.org/1999/xlink");

            Assert.True((bool)navigator.Evaluate("1=count(/link[@xlink:href='#abc123'][@xlink:title='Example'][@xlink:type='simple'])", namespaces));
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new XLink());
        }

        [Fact]
        public void prop_XmlNamespaceDeclarations()
        {
            Assert.True(new PropertyExpectations(typeof(XLink).GetProperty("XmlNamespaceDeclarations"))
                .XmlNamespaceDeclarations()
                .TypeIs<XmlSerializerNamespaces>()
                .DefaultValueIsNotNull()
                .Result);
        }

        [Fact]
        public void prop_XmlNamespaceDeclarations_get()
        {
            XmlSerializerNamespaces actual = new XLink().XmlNamespaceDeclarations;

            Assert.Equal<int>(1, actual.Count);

            XmlQualifiedName name = actual.ToArray().GetValue(0) as XmlQualifiedName;
            Assert.Equal<string>("xlink", name.Name);
            Assert.Equal<string>("http://www.w3.org/1999/xlink", name.Namespace);
        }

        [Fact]
        public void prop_Href()
        {
            Assert.True(new PropertyExpectations(typeof(XLink).GetProperty("Href"))
                .XmlAttribute("href", "http://www.w3.org/1999/xlink")
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Title()
        {
            Assert.True(new PropertyExpectations(typeof(XLink).GetProperty("Title"))
                .XmlAttribute("title", "http://www.w3.org/1999/xlink")
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Type()
        {
            Assert.True(new PropertyExpectations(typeof(XLink).GetProperty("Type"))
                .XmlAttribute("type", "http://www.w3.org/1999/xlink")
                .TypeIs<string>()
                .Set("simple")
                .Set("extended")
                .Set("locator")
                .Set("arc")
                .Set("resource")
                .Set("title")
                .ArgumentOutOfRangeException(string.Empty)
                .ArgumentOutOfRangeException("foo")
                .Result);
        }
    }
}